package com.webchat.connect.websocket.handler;

import com.webchat.common.enums.ChatMessageTypeEnum;
import com.webchat.common.enums.RedisMessageChannelTopicEnum;
import com.webchat.common.enums.RoleCodeEnum;
import com.webchat.common.enums.VideoSDPMessageType;
import com.webchat.common.enums.messagequeue.MessageBroadChannelEnum;
import com.webchat.common.service.messagequeue.producer.MessageQueueProducer;
import com.webchat.common.util.JsonUtil;
import com.webchat.connect.service.AccountService;
import com.webchat.domain.vo.request.mess.ChatMessageRequestVO;
import com.webchat.domain.vo.request.mess.MessageNotifyVO;
import com.webchat.domain.vo.request.mess.VideoChatMessageRequestVO;
import com.webchat.domain.vo.response.UserBaseResponseInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class P2PVideoWebSocketEndPointServletHandler extends TextWebSocketHandler {

    @Autowired
    private MessageQueueProducer<Object, Long> messageQueueProducer;

    @Autowired
    private AccountService accountService;

    /**
     * Map<KEY1, Map<KEY2, WebSocketSession>>
     *
     * KEY1：用于区分场景，如：PC-APP、 PC-CHAT、WAP-APP ，详见：WebSocketBizCodeEnum
     * KEY2: 用户
     * WebSocketSession: 不同场景下用户的WebSocket Session对象 -- 全双工、有状态
     */
    public static Map<String, Map<String, WebSocketSession>> sessions = new ConcurrentHashMap<>();

    /**
     * 连接建立
     *
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 获取路径参数
        Map<String, Object> attributes = session.getAttributes();
        String bizCode = (String) attributes.get("bizCode");
        String userId = (String) attributes.get("userId");
        Map<String, WebSocketSession> userSessions = sessions.get(bizCode);
        if (userSessions == null) {
            userSessions = new ConcurrentHashMap<>();
            sessions.put(bizCode, userSessions);
        }
        userSessions.put(userId, session);
        log.info("Chat WebSocket connection ====> userId:{}, sessionId:{}", userId, session.getId());
    }

    /**
     * 收到消息
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        System.out.println("Chat WebSocket Connection Received message: " + payload);
        if ("ping".equals(payload)) {
            // 心跳检测
            return;
        }
        VideoChatMessageRequestVO videoMessage = JsonUtil.fromJson(payload, VideoChatMessageRequestVO.class);
        if (VideoSDPMessageType.call.name().equals(videoMessage.getType())) {
            /**
             * 1. 给被呼叫人推送呼叫提醒
             */
            UserBaseResponseInfoVO sender = accountService.accountInfo(videoMessage.getUserId());
            MessageNotifyVO messageBase = new MessageNotifyVO();
            messageBase.setSender(sender);
            messageBase.setReceiverId(videoMessage.getTargetUserId());
            messageBase.setType(ChatMessageTypeEnum.VIDEO_CALL.getType());
            /**
             * 广播音视频呼叫信息给被呼人
             */
            messageQueueProducer.broadSend(MessageBroadChannelEnum.QUEUE_CHAT_NOTIFY, messageBase);
            return;
        }
        /**
         * 2. 信命推送
         */
        messageQueueProducer.broadSend(MessageBroadChannelEnum.QUEUE_VIDEO_SDP, videoMessage);
    }

    /**
     * 断开连接
     *
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("Chat WebSocket Connection closed: " + session.getId());
    }

    public static WebSocketSession getSession(String bizCode, String userId) {
        if (StringUtils.isBlank(bizCode) || StringUtils.isBlank(userId)) {
            return null;
        }
        Map<String, WebSocketSession> userSessions = sessions.get(bizCode);
        if (MapUtils.isEmpty(userSessions)) {
            return null;
        }
        return userSessions.get(userId);
    }
}
